package cn.peach.hrm.service.impl;

import cn.peach.hrm.config.HighlightResultMapper;
import cn.peach.hrm.doc.CourseDoc;
import cn.peach.hrm.dto.CourseSearchDto;
import cn.peach.hrm.repository.CourseElasticsearchRepository;
import cn.peach.hrm.service.ICourseESService;
import cn.peach.hrm.util.PageList;
import cn.peach.hrm.vo.AggPageList;
import cn.peach.hrm.vo.TermsAggBucket;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author you
 * @create 2021/11/28 16:17
 */
@Service
public class CourseESServiceImpl implements ICourseESService {
    @Autowired
    private CourseElasticsearchRepository repository;

    @Autowired
    private ElasticsearchTemplate template;

    @Autowired
    private HighlightResultMapper resultMapper;

    @Override
    public void save(CourseDoc courseDoc) {
        repository.save(courseDoc);
    }

    @Override
    public PageList<CourseDoc> search(CourseSearchDto dto) {
        // 查询条件构建器
        NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();
        // 排序
        if (StringUtils.isNotEmpty(dto.getSortField())){
            String sortField = "onlineTime";
            switch (dto.getSortField()){
                case "jg": sortField = "price";break;
                case "xl": sortField = "saleCount";break;
                case "pl": sortField = "commentCount";break;
                case "rq": sortField = "viewCount";break;
                case "xp": sortField = "onlineTime";break;
            }
            SortOrder sortOrder = SortOrder.DESC;
            if(dto.getSortType() != null && dto.getSortType().equalsIgnoreCase("asc")){
                sortOrder = SortOrder.ASC;
            }
            searchQueryBuilder.withSort(SortBuilders.fieldSort(sortField).order(sortOrder));
        }

        // 分页
        searchQueryBuilder.withPageable(PageRequest.of(dto.getPage() - 1, dto.getRows()));

        // 组合查询
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        // 添加keyword
        if(StringUtils.isNotEmpty(dto.getKeyword())){
            boolQueryBuilder.must(QueryBuilders.matchQuery("name", dto.getKeyword()));
        }
        // 添加filter 课程分类ID
        if(null != dto.getCourseTypeId()){
            boolQueryBuilder.filter(QueryBuilders.termQuery("courseTypeId", dto.getCourseTypeId()));
        }
        // 等级名
        if(StringUtils.isNotEmpty(dto.getGradeName())){
            boolQueryBuilder.filter(QueryBuilders.termQuery("gradeName", dto.getGradeName()));
        }
        // 机构名
        if(StringUtils.isNotEmpty(dto.getTenantName())){
            boolQueryBuilder.filter(QueryBuilders.termQuery("tenantName", dto.getTenantName()));
        }
        // 价格查询
        if(null != dto.getPriceMax()){
            boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").lte(dto.getPriceMax()));
        }
        if(null != dto.getPriceMin()){
            boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(dto.getPriceMin()));
        }
        // 关联查询条件
        searchQueryBuilder.withQuery(boolQueryBuilder);

        // 设置高亮
        HighlightBuilder.Field field = new HighlightBuilder.Field("name")
                .preTags("<span style='color:red'>")
                .postTags("</span>");
        searchQueryBuilder.withHighlightFields(field);

        /**
         * 聚合
         */
        // 等级聚合
        TermsAggregationBuilder gradeNameAgg = AggregationBuilders.terms("gradeNameAgg").field("gradeName");
        TermsAggregationBuilder tenantNameAgg = AggregationBuilders.terms("tenantNameAgg").field("tenantName");
        searchQueryBuilder.addAggregation(gradeNameAgg).addAggregation(tenantNameAgg);

        // 聚合结果
        AggregatedPage<CourseDoc> page = template.queryForPage(searchQueryBuilder.build(), CourseDoc.class, resultMapper);
        Map<String, List<TermsAggBucket>> termsAggResult = new HashMap<>();
        // 结果处理
        Map<String, Aggregation> aggregationMap = page.getAggregations().asMap();
        aggregationMap.keySet().forEach(key->{
            // Bucke列表
            List<TermsAggBucket> termsAggBuckets = new ArrayList<>();
            // key 聚合的名字
            // value：aggregation
            StringTerms aggregation = (StringTerms) aggregationMap.get(key);
            aggregation.getBuckets().forEach(bucket -> {
                String name = bucket.getKey().toString();
                // 数量
                long docCount = bucket.getDocCount();
                // Bucket转成TermsAggBucket对象
                termsAggBuckets.add(new TermsAggBucket(name , docCount));
            });
            // 添加到聚合结果里
            termsAggResult.put(key,termsAggBuckets );
        });
        return new AggPageList(page.getTotalElements() , page.getContent(),termsAggResult);
    }
}
